#include "stdafx.h"

#pragma comment(lib,"gdiplus")

using namespace Gdiplus;

// functions
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
void update();
void save();
int getBin(bool arr[]);

// constants
const int XSCREEN = GetSystemMetrics(SM_CXSCREEN);
const int YSCREEN = GetSystemMetrics(SM_CYSCREEN);
const int XWINDOW = 1000;
const int YWINDOW = YSCREEN;
const int WALL = 1;
const int STEEL = 2;
const int WATER = 3;
const int ERASER = 4;
Image * imgWall;
Image * imgSteel;
Image * imgWater;

// 
HWND hwnd;
HDC hdc;
Graphics * graphics;
HDC memDC;

bool wall[26][26] = { 0 };
bool steel[26][26] = { 0 };
bool water[26][26] = { 0 };
int cur = ERASER;

struct GdipInit
{
	GdipInit()
	{
		GdiplusStartupInput gsi;
		ULONG_PTR token;
		GdiplusStartup(&token, &gsi, NULL);
	}
} init;

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE prevInstance, LPSTR cmdline, int cmdShow)
{
	WNDCLASSEX wc = { 0 };
	wc.cbSize = sizeof(WNDCLASSEX);
	wc.hCursor = LoadCursor(hInstance, IDC_ARROW);
	wc.hIcon = wc.hIconSm = LoadIcon(hInstance, IDI_APPLICATION);
	wc.hInstance = hInstance;
	wc.lpfnWndProc = WndProc;
	wc.lpszClassName = L"Window";
	RegisterClassEx(&wc);
	hwnd = CreateWindowEx(0, L"Window", L"eraser", WS_OVERLAPPEDWINDOW, 0, 0, XWINDOW, YWINDOW, NULL, NULL, hInstance, NULL);
	UpdateWindow(hwnd);
	ShowWindow(hwnd, 1);

	hdc = GetDC(hwnd);
	memDC = CreateCompatibleDC(hdc);
	HBITMAP bmp = CreateCompatibleBitmap(hdc, XWINDOW, YWINDOW);
	SelectObject(memDC, bmp);
	DeleteObject(bmp);
	graphics = new Graphics(memDC);
	graphics->Clear(0xffffffff);

	imgWall = new Image(L"img\\wall.png");
	imgSteel = new Image(L"img\\steel.png");
	imgWater = new Image(L"img\\water.png");

	for (int i = 0; i < 25; i++)
	{
		steel[0][i] = true;
		steel[i][25] = true;
		steel[25][i + 1] = true;
		steel[i + 1][0] = true;
	}
	update();

	MSG msg;
	while (GetMessage(&msg, 0, 0, 0))
	{
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}

	return 0;
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	switch (message)
	{
	case WM_CREATE:
		
		break;
	case WM_DESTROY:
		delete graphics;
		ReleaseDC(hwnd, hdc);
		PostQuitMessage(0);
		break;
	case WM_PAINT:
		BitBlt(hdc, 0, 0, XWINDOW, YWINDOW, memDC, 0, 0, SRCCOPY);
		break;
	case WM_KEYDOWN:
		switch (wParam)
		{
		case '1':
			cur = WALL;
			SetWindowText(hwnd, L"wall");
			break;
		case '2':
			cur = STEEL;
			SetWindowText(hwnd, L"steel");
			break;
		case '3':
			cur = WATER;
			SetWindowText(hwnd, L"water");
			break;
		case '4':
			cur = ERASER;
			SetWindowText(hwnd, L"eraser");
			break;
		case 'S':
			save();
			break;
		}
		break;
	case WM_LBUTTONDOWN:
	{
		int x = LOWORD(lParam) / 30;
		int y = HIWORD(lParam) / 30;

		if (x >= 1 && x < 25 && y >= 1 && y < 25)
		{
			switch (cur)
			{
			case WALL:
				wall[y][x] = true;
				steel[y][x] = false;
				water[y][x] = false;
				break;
			case STEEL:
				steel[y][x] = true;
				wall[y][x] = false;
				water[y][x] = false;
				break;
			case WATER:
				water[y][x] = true;
				wall[y][x] = false;
				water[y][x] = false;
				break;
			case ERASER:
				wall[y][x] = false;
				steel[y][x] = false;
				water[y][x] = false;
				break;
			}
			
			update();
		}
		
		break;
	}
	case WM_MOUSEMOVE:
	{
		int x = LOWORD(lParam) / 30;
		int y = HIWORD(lParam) / 30;

		TCHAR temp[50];
		swprintf_s(temp, L"(%d,%d)", x, y);
		TextOut(hdc, 900, 0, temp, 10);

		if (x >= 1 && x < 25 && y >= 1 && y < 25 && wParam & MK_LBUTTON)
		{
			switch (cur)
			{
			case WALL:
				wall[y][x] = true;
				steel[y][x] = false;
				water[y][x] = false;
				break;
			case STEEL:
				steel[y][x] = true;
				wall[y][x] = false;
				water[y][x] = false;
				break;
			case WATER:
				water[y][x] = true;
				wall[y][x] = false;
				steel[y][x] = false;
				break;
			case ERASER:
				wall[y][x] = false;
				steel[y][x] = false;
				water[y][x] = false;
				break;
			}

			update();
		}

		InvalidateRect(hwnd, NULL, TRUE);
		break;
	}
	default:
		return DefWindowProc(hwnd, message, wParam, lParam);
	}

	return 0;
}

void update()
{
	graphics->Clear(0xffffffff);
	for (int i = 0; i < 26; i++)
	{
		for (int j = 0; j < 26; j++)
		{
			if (steel[i][j])
			{
				graphics->DrawImage(imgSteel, j * 30, i * 30, 30, 30);
			}
			if (wall[i][j])
			{
				graphics->DrawImage(imgWall, j * 30, i * 30, 30, 30);
			}
			if (water[i][j])
			{
				graphics->DrawImage(imgWater, j * 30, i * 30, 30, 30);
			}
		}
	}

	InvalidateRect(hwnd, NULL, TRUE);
}

void save()
{
	std::wstring filename = L"map.xml";
	std::wofstream file{ filename };

	file << L"<map>\n\t<wall>\n";
	for (int i = 0; i < 26; i++)
	{
		file << L"\t\t<line>" << getBin(wall[i]) << L"</line>\n";
	}
	file << L"\t</wall>\n\t<steel>\n";
	for (int i = 0; i < 26; i++)
	{
		file << L"\t\t<line>" << getBin(steel[i]) << L"</line>\n";
	}
	file << L"\t</steel>\n\t<water>\n";
	for (int i = 0; i < 26; i++)
	{
		file << L"\t\t<line>" << getBin(water[i]) << L"</line>\n";
	}
	file << L"\t</water>\n</map>";

	file.close();
}

int getBin(bool arr[])
{
	int ans = 0;

	for (int i = 0; i < 26; i++)
	{
		ans += arr[i] * pow(2, 25 - i);
	}

	return ans;
}